package android.slc.appbase.ui.widget.slider;

import javafx.css.PseudoClass;
import javafx.geometry.Orientation;
import javafx.scene.control.Slider;
import javafx.scene.control.skin.SliderSkin;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;

/**
 * @author slc
 * @date 2022/09/27 下午 2:18
 */
public class SimpleJFXSliderSkin extends SliderSkin {

    private final Pane mouseHandlerPane = new Pane();
    private static final PseudoClass MIN_VALUE = PseudoClass.getPseudoClass("min");
    private static final PseudoClass MAX_VALUE = PseudoClass.getPseudoClass("max");

    private StackPane coloredTrack;
    private StackPane thumb;
    private StackPane track;

    public SimpleJFXSliderSkin(Slider slider) {
        super(slider);

        track = (StackPane) getSkinnable().lookup(".track");
        thumb = (StackPane) getSkinnable().lookup(".thumb");

        coloredTrack = new StackPane();
        coloredTrack.getStyleClass().add("colored-track");
        coloredTrack.setMouseTransparent(true);

        getChildren().add(getChildren().indexOf(thumb), coloredTrack);
        getChildren().add(0, mouseHandlerPane);


        initListeners();
    }

    @Override
    protected void layoutChildren(double x, double y, double w, double h) {
        super.layoutChildren(x, y, w, h);
        boolean horizontal = getSkinnable().getOrientation() == Orientation.HORIZONTAL;
        double width, height, layoutX, layoutY;
        if (horizontal) {
            width = thumb.getLayoutX() - snappedLeftInset();
            height = track.getHeight();
            layoutX = track.getLayoutX();
            layoutY = track.getLayoutY();
        } else {
            height = track.getLayoutBounds().getMaxY() + track.getLayoutY() - thumb.getLayoutY() - snappedBottomInset();
            width = track.getWidth();
            layoutX = track.getLayoutX();
            layoutY = thumb.getLayoutY();
        }

        coloredTrack.resizeRelocate(layoutX, layoutY, width, height);
        mouseHandlerPane.resizeRelocate(x, y, w, h);
    }

    private void initListeners() {
        // delegate slider mouse events to track node
        mouseHandlerPane.setOnMousePressed(this::delegateToTrack);
        mouseHandlerPane.setOnMouseReleased(this::delegateToTrack);
        mouseHandlerPane.setOnMouseDragged(this::delegateToTrack);

        updateValueStyleClass();

        getSkinnable().valueProperty().addListener(observable -> updateValueStyleClass());
    }

    private void delegateToTrack(MouseEvent event) {
        if (!event.isConsumed()) {
            event.consume();
            track.fireEvent(event);
        }
    }

    private void updateValueStyleClass() {
        getSkinnable().pseudoClassStateChanged(MIN_VALUE, getSkinnable().getMin() == getSkinnable().getValue());
        getSkinnable().pseudoClassStateChanged(MAX_VALUE, getSkinnable().getMax() == getSkinnable().getValue());
    }


}
